package com.jyxd.web.util;

import cn.hutool.core.util.ArrayUtil;
import com.jyxd.web.error.JyxdException;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Collection;
import java.util.Map;
import java.util.function.Function;

public class ExecuteUtil {

    private static Logger logger = LoggerFactory.getLogger(ExecuteUtil.class);

    public interface ExecuteReturn<T> {
        T exec();
    }

    public interface Execution {
        void exec();
    }

    public static void executeIfTrue(Boolean isTrue, Execution exec) {
        if (BooleanUtils.toBoolean(isTrue)) {
            exec.exec();
        }
    }

    public static void executeIfFalse(Boolean isFalse, Execution exec) {
        if (BooleanUtils.isNotTrue(isFalse)) {
            exec.exec();
        }
    }

    public static void executeIfEmpty(Object value, Execution exec) {
        if (isEmpty(value)) {
            exec.exec();
        }
    }

    public static void executeIfNotEmpty(Object value, Execution exec) {
        if (isNotEmpty(value)) {
            exec.exec();
        }
    }

    public static boolean isNotEmpty(Object value) {
        return !isEmpty(value);
    }

    public static boolean isEmpty(Object value) {
        if (value == null) {
            return true;
        }
        if (value.getClass().isArray()) {
            Object[] arr = (Object[]) value;
            return ArrayUtil.isEmpty(arr);
        }
        if (value instanceof String && StringUtils.isBlank((String) value)) {
            return true;
        }
        if (value instanceof Collection && CollectionUtils.isEmpty((Collection) value)) {
            return true;
        }
        if (value instanceof Map && MapUtils.isEmpty((Map) value)) {
            return true;
        }
        return false;
    }

    public static void errorIfEmpty(Object value, int code, String fmt, Object... args) {
        if (isEmpty(value)) {
            String error = String.format(fmt, args);
            throw new JyxdException(code, error);
        }
    }

    public static void errorIfEmpty(Object value, String fmt, Object... args) {
        if (isEmpty(value)) {
            String error = String.format(fmt, args);
            throw new JyxdException(error);
        }
    }

    public static void errorIfNotEmpty(Object value, String fmt, Object... args) {
        if (isNotEmpty(value)) {
            String error = String.format(fmt, args);
            throw new JyxdException(error);
        }
    }


    public static void errorIfFalse(Boolean isTrue, String fmt, Object... args) {
        if (!BooleanUtils.toBoolean(isTrue)) {
            String error = String.format(fmt, args);
            throw new JyxdException(error);
        }
    }

    public static void errorIfFalse(Boolean isTrue, int errorCode, String fmt, Object... args) {
        if (!BooleanUtils.toBoolean(isTrue)) {
            String error = String.format(fmt, args);
            throw new JyxdException(errorCode, error);
        }
    }

    public static void errorIfHere(String fmt, Object... args) {
        String error = String.format(fmt, args);
        throw new JyxdException(error);
    }

    public static void errorIfTrue(Boolean isTrue, String fmt, Object... args) {
        if (BooleanUtils.toBoolean(isTrue)) {
            String error = String.format(fmt, args);
            throw new JyxdException(error);
        }
    }

    public static class ExceptionReporter {
        private final String prefix;
        private StringBuilder exceptionBuffer = new StringBuilder();

        public ExceptionReporter(String prefix) {
            this.prefix = prefix;
        }

        public static ExceptionReporter Expt(String prefix) {
            return new ExceptionReporter(prefix);
        }

        public static ExceptionReporter Expt() {
            return new ExceptionReporter(null);
        }

        public ExceptionReporter errorIfEmpty(Object value, String fmt, Object... args) {
            if (isEmpty(value)) {
                if (exceptionBuffer.length() > 0) {
                    exceptionBuffer.append(",");
                }
                String error = String.format(fmt, args);
                logger.error("(REPORT ERR) {}", error);
                exceptionBuffer.append(error);
            }
            return this;
        }

        public ExceptionReporter errorIfFieldEmpty(Object value, String fieldName) {
            return errorIfEmpty(value, "%s不能为空", fieldName);
        }

        public ExceptionReporter errorIfTrue(Boolean isTrue, String fmt, Object... args) {
            if (BooleanUtils.toBoolean(isTrue)) {
                if (exceptionBuffer.length() > 0) {
                    exceptionBuffer.append(",");
                }
                String error = String.format(fmt, args);
                logger.error("(REPORT ERR) {}", error);
                exceptionBuffer.append(error);
            }
            return this;
        }

        public ExceptionReporter errorIfFalse(Boolean isTrue, String fmt, Object... args) {
            return errorIfTrue(!isTrue, fmt, args);
        }

        public void report() {
            if (exceptionBuffer.length() > 0) {
                throw new JyxdException(getNullableOf(prefix, p -> p + " ", StringUtils.EMPTY) + exceptionBuffer.toString());
            }
        }
    }

    public static <T, S> T getNullableOf(S object, Function<S, T> func, T defaultValue) {
        return isNotEmpty(object) ? func.apply(object) : defaultValue;
    }


}
